package com.joney.backstage.service;

import com.baomidou.mybatisplus.plugins.Page;
import com.google.gson.Gson;
import com.joney.backstage.constant.Constants;
import com.joney.backstage.constant.Permissions;
import com.joney.backstage.constant.WebPageEL;
import com.joney.backstage.dto.Login4InnerFrameReq;
import com.joney.backstage.dto.LoginReq;
import com.joney.backstage.dto.UserEditReq;
import com.joney.backstage.dto.UserRoleRsp;
import com.joney.backstage.entity.User;
import com.joney.backstage.entity.UserLoginRecord;
import com.joney.backstage.entity.enums.TokenStatusEnum;
import com.joney.backstage.mapper.UserMapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.joney.common.exception.DefaultException;
import com.joney.common.pojo.Result;
import com.joney.common.pojo.UserSession;
import com.joney.common.utils.EncryptUtil;
import com.joney.common.utils.JwtToken;
import com.joney.common.utils.MD5Util;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 帐户表 服务实现类
 * </p>
 *
 * @author joney123
 * @since 2018-01-17
 */
@Service
public class UserService extends ServiceImpl<UserMapper, User>{

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private UserLoginRecordService userLoginRecordService;

    private CacheManager manager = CacheManager.getInstance();

    public String login(LoginReq loginReq,String ip){
        Cache cache = manager.getCache(Constants.CACHE_KEY_OF_CHECK_CODE);
        Element element = cache.get(loginReq.getCheckId());
        if(element == null || !loginReq.getCheckCode().equalsIgnoreCase(element.getObjectValue().toString())){
            throw new DefaultException("验证码不对");
        }
        User user = this.findByLoginName(loginReq.getUserName());
        if(user == null){
            throw new DefaultException("帐户不存在");
        }
        if(user.getState().equals(TokenStatusEnum.INVALID.getIntValue())){
            throw new DefaultException("帐户已失效，请联系管理员");
        }
        if(!MD5Util.encode(loginReq.getPassword()).equals(user.getPassword())){
            throw new DefaultException("用户名或密码不对");
        }
        return tokenHandle(user,ip);
    }

    public String innerFrameLogin(Login4InnerFrameReq req, String ip){
        User user = this.selectById(req.getUserId());
        if(user == null){
            throw new DefaultException("帐户不存在");
        }
        if(!MD5Util.encode(req.getPassword()).equals(user.getPassword())){
            throw new DefaultException("密码不对");
        }
        return tokenHandle(user,ip);
    }

    private String tokenHandle(User user,String ip){
        UserSession session = new UserSession();
        session.setUid(Long.valueOf(user.getId()));
        session.setUname(user.getLoginName());
        String token;
        try {
            token = JwtToken.sign(new Gson().toJson(session));
        } catch (Exception e) {
            throw new DefaultException("系统异常");
        }
        //更新同一个IP的token状态
        List<UserLoginRecord> lastLoginList = userLoginRecordService.getLastLoginRecordByIp(user.getId(),ip);
        Cache tokenCache = manager.getCache(Constants.CACHE_KEY_OF_USER_TOKEN);
        if(lastLoginList != null && lastLoginList.size()>0){
            for(UserLoginRecord record : lastLoginList){
                tokenCache.remove(record.getToken());
                record.setUserId(null);
                record.setLoginName(null);
                record.setIp(null);
                record.setToken(null);
                record.setLoginTime(null);
                record.setTokenStatus(TokenStatusEnum.INVALID.getIntValue());
            }
            userLoginRecordService.updateBatchById(lastLoginList,lastLoginList.size());
        }
        tokenCache.put(new Element(token, null));
        UserLoginRecord record = new UserLoginRecord();
        record.setUserId(user.getId());
        record.setLoginName(user.getLoginName());
        record.setIp(ip);
        record.setToken(token);
        record.setTokenStatus(TokenStatusEnum.NORMAL.getIntValue());
        userLoginRecordService.insert(record);
        return token;
    }


    public void logout(String token){
        Cache tokenCache = manager.getCache(Constants.CACHE_KEY_OF_USER_TOKEN);
        tokenCache.remove(token);
        userLoginRecordService.updateTokenStatusByToken(token);
    }
    public Map<String,Boolean> getMgrPermission(int curLoginUserId){
        Map<String,Boolean> authMap = new HashMap<>();
        authMap.put(WebPageEL.CAN_ADD,false);
        authMap.put(WebPageEL.CAN_EDIT,false);
        authMap.put(WebPageEL.CAN_DEL,false);
        authMap.put(WebPageEL.CAN_ROLE_OPT,false);
        authMap.put(WebPageEL.CAN_USER_BIND_ROLE_OPT,false);
        List<String> permissionList = userRoleService.getPermissions(curLoginUserId);
        if(permissionList != null && permissionList.size() > 0){
            for(String permission : permissionList){
                  if(permission != null){
                      if(permission.equals(Permissions.SYS_USER_ADD)){
                          authMap.put(WebPageEL.CAN_ADD,true);
                      }else if(permission.equals(Permissions.SYS_USER_EDIT)){
                          authMap.put(WebPageEL.CAN_EDIT,true);
                      }else if(permission.equals(Permissions.SYS_USER_DEL)){
                          authMap.put(WebPageEL.CAN_DEL,true);
                      }else if(permission.equals(Permissions.SYS_USER_ROLE_VIEW)){
                          authMap.put(WebPageEL.CAN_ROLE_OPT,true);
                      }else if(permission.equals(Permissions.SYS_USER_ROLE_BIND)){
                          authMap.put(WebPageEL.CAN_USER_BIND_ROLE_OPT,true);
                      }
                  }
            }
        }
        return authMap;
    }
    public User findByLoginName(String loginName) {
        User temp = new User();
        temp.setLoginName(loginName);
        return baseMapper.selectOne(temp);
    }

    /**
     * 更新用户信息
     * @param params
     * @param updateUserId
     * @return
     */
    public Result updateUser(UserEditReq params, int updateUserId){
        User user = baseMapper.selectById(params.getId());
        if(user == null){
            return Result.fail("不存在的用户");
        }
        user = new User();
        BeanUtils.copyProperties(params,user);
        user.setUpdateUser(updateUserId);
        baseMapper.updateById(user);
        return Result.success();
    }

    public Result changePwd(String param, String token){
        Long currentUserId = JwtToken.unsign(token).getUid();
        User user = selectById(currentUserId);
        if(user == null){
            throw new DefaultException("帐户不存在");
        }
        HashMap<String,String> paramMap = null;
        try {
            String json = EncryptUtil.aesDecrypt(param);
            paramMap = new Gson().fromJson(json,HashMap.class);
        } catch (Exception e) {
            throw new DefaultException("解析参数失败");
        }
        if(!MD5Util.encode(paramMap.get("oldPwd").toString()).equals(user.getPassword())){
            throw new DefaultException("旧密码不对");
        }
        User temp = new User();
        temp.setId(user.getId());
        temp.setPassword(MD5Util.encode(paramMap.get("newPwd").toString()));
        temp.setUpdateUser(currentUserId.intValue());
        if(!updateById(temp)){
            return Result.fail("保存失败");
        }
        logout(token);
        return Result.success();
    }


    public Result bindRole(int userId, int bindState, String roleIds, int operatorId){
        return userRoleService.bindRole(userId,bindState,roleIds,operatorId);
    }

    public List<UserRoleRsp> queryBind(Page page, Map<String,Object> params){
        return userRoleService.queryBind(page,params);
    }

    public List<UserRoleRsp> queryNotBindRole(Page page, Map<String,Object> params){
        return userRoleService.queryNotBindRole(page,params);
    }
}
